Unions with Parametric Polymorphism (Parapoly)
Error :: enum {Foo0, Foo1, Foo2}
Param_Union :: union($T: typeid) #no_nil {T, Error}
r: Param_Union(int)
r = 123
r = Error.Foo0
Union Casting
-
Limitations with Pointer Casting :
-
Caio:
-
how do I convert a 'pointer to a value', to a 'pointer to a union'? I'm doing
cast(^My_Union)value, wherevalue: ^$T, withTbeing a generic parameter for a procedure, but I'm getting an "index out of bounds" error while trying to cast a[2]f32
-
-
Blob:
-
you can't, unions are
<data><tag>. meaning they're bigger than their types. the tag is just an index into an array in the RTTI. -
except for unions with only a single pointer type
union{^T}where the tag is dropped & the nil check just checks if the pointer is nil.
-
-
-
Union type :
fmt.printfln("%T", my_union)
// or
fmt.printfln("%v", typeid_of(type_of(my_union)))
-
Unwrapped Union type :
fmt.printfln("%v", reflect.union_variant_typeid(my_union))
Type check
Via
value.(T)
Value :: union {
bool,
i32,
f32,
string,
}
v: Value
v = "Hellope"
// type assert that `v` is a `string` and panic otherwise.
s1 := v.(string)
// type assert but with an explicit BOOLEAN check. This will not panic.
s2, ok := v.(string)
if !ok {
// problem encountered.
}
Via Switch Statement
-
A type switch allows several type assertions in series.
-
A type switch is like a regular switch, but the cases are types (not values).
-
For a union, only the union's types are allowed as case types.
value: Value = ...
switch v in value {
case string:
#assert(type_of(v) == string)
case bool:
#assert(type_of(v) == bool)
case i32, f32:
// This case allows multiple types, therefore we cannot know which type to use
// `v` remains the original union value
#assert(type_of(v) == Value)
case:
// Default case
// In this case, it is `nil`
}
Maybe
-
Maybe .
-
A union which either returns a type
Tornil. In other languages, often seen asOption(T),Result(T), etc. -
Not used much, as Odin supports multiple return values.
halve :: proc(n: int) -> Maybe(int) {
if n % 2 != 0 do return nil
return n / 2
}
half, ok := halve(2).?
if ok do fmt.println(half) // 1
half, ok = halve(3).?
if !ok do fmt.println("3/2 isn't an int")
n := halve(4).? or_else 0
fmt.println(n) // 2